package com.yiba.vpn.util.location;

import com.yiba.www.pojo.IPLLData;

import java.io.File;

public class IPLLDecodeUtils {

    //    private static final String BASE_PATH = PathUtils.getBasePath();
    private static final String BASE_PATH = "/data/";
    private static final String ALL_DATA_OBJ = BASE_PATH + "all_data.obj";
    private static final String IP_SPLIT = "\\.";
    private static final String IP_ZERO = "0.0.0.0";
    private static IPLLDecodeUtils ipllDecodeUtils = new IPLLDecodeUtils();
    private IPLLData ipllData;


    private IPLLDecodeUtils() {
        initData();
    }

    //获取对象，也是初始化方法
    public static IPLLDecodeUtils getInstance() {
        return ipllDecodeUtils;
    }

    //解码经纬度，无法解析时返回空
    public IPLLData.Location decodeLL(double lat, double lng) {
//        long start = System.currentTimeMillis();
        IPLLData.Location result = null;
        if (ipllData != null) {
            IPLLData.LLICC llicc = sureLLICC(lat, lng);
            if (llicc != null) {
                result = ipllData.getLocations()[llicc.getId()];
            }
        } else {
            System.out.println("iplliccBuilder is null.");
        }
//        System.out.println("time=" + (System.currentTimeMillis() - start));
        return result;
    }

    //获取是否加载成功
    public boolean isInitOk() {
        return ipllData != null;
    }

    public void updateData() {
        initData();
    }

    //解码IP，无法解析时返回空
    public IPLLData.Location decodeIP(String ip) {
//        long start = System.currentTimeMillis();
        IPLLData.Location result = null;
        int resultLineNumber = IPUtils.ip2Key(ip);
        if (resultLineNumber == 0 && !IP_ZERO.equals(ip)) {
            System.out.println("ip is error. ip =" + ip);
        } else {
            if (ipllData != null) {
                result = ipllData.getLocations()[ipllData.getIps()[resultLineNumber]];
            } else {
                System.out.println("iplliccBuilder is null." + ip);
            }
        }
//        System.out.println("time=" + (System.currentTimeMillis() - start));
        return result;
    }

    //真实调用的初始化方法
    private void initData() {
        File file = new File(ALL_DATA_OBJ);
        ipllData = FileUtils.file2Object(file);
    }

    private IPLLData.LLICC sureLLICC(double lat, double lng) {
        int a = (int) ((lat + 90) / 10);
        int b = ((int) ((lng + 180) / 10));
        String key = (a - 1) + "-" + (b - 1);
        IPLLData.LLICC result = sureLLICC(key, lat, lng, null);
        key = (a - 1) + "-" + b;
        result = sureLLICC(key, lat, lng, result);
        key = (a - 1) + "-" + (b + 1);
        result = sureLLICC(key, lat, lng, result);
        key = a + "-" + (b - 1);
        result = sureLLICC(key, lat, lng, result);
        key = a + "-" + b;
        result = sureLLICC(key, lat, lng, result);
        key = a + "-" + (b + 1);
        result = sureLLICC(key, lat, lng, result);
        key = (a + 1) + "-" + (b - 1);
        result = sureLLICC(key, lat, lng, result);
        key = (a + 1) + "-" + b;
        result = sureLLICC(key, lat, lng, result);
        key = (a + 1) + "-" + (b + 1);
        result = sureLLICC(key, lat, lng, result);
//        System.out.println("sureLLICC lat=" + lat + ";lng=" + lng + ";result=" + result);
        return result;
    }

    private IPLLData.LLICC sureLLICC(String key, double lat, double lng, IPLLData.LLICC lastMin) {
        double last = 0;
        double current;
        IPLLData.LLICC tempLLICC = null;
        IPLLData.LLICC[] tempLLICCs = ipllData.getLliccMap().get(key);
        if (tempLLICCs != null) {
            for (IPLLData.LLICC llicc : tempLLICCs) {
                current = (llicc.getLat() - lat) * (llicc.getLat() - lat) + (llicc.getLng() - lng) * (llicc.getLng() - lng);
                if (current < last || last == 0) {
                    tempLLICC = llicc;
                    last = current;
                }
            }
        }
        if (lastMin != null) {
            if (tempLLICC != null) {
                if (((lastMin.getLat() - lat) * (lastMin.getLat() - lat) + (lastMin.getLng() - lng) * (lastMin.getLng() - lng))
                        < ((tempLLICC.getLat() - lat) * (tempLLICC.getLat() - lat) + (tempLLICC.getLng() - lng) * (tempLLICC.getLng() - lng))) {
                    tempLLICC = lastMin;
                }
            } else {
                tempLLICC = lastMin;
            }
        }
        return tempLLICC;
    }

}
